#pragma once
#include <zlib.h>
#include "SQLite/sqlite3.h"
#include "../Algo/base.h"

using namespace std;
using namespace REC3D;

class Db
{
public:
	string db_name;

	inline Db() {};

	inline Db(string sDbName)
	{
		db_name = sDbName;
	};

	sqlite3* database_ = nullptr;
	vector<sqlite3_stmt*> sql_stmts_;
	
	// 特征提取相关sql
	sqlite3_stmt* sql_stmt_WriteImageName_ = nullptr;
	sqlite3_stmt* sql_stmt_ExistImageName_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadImageID_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadImageName_ = nullptr;	
	sqlite3_stmt* sql_stmt_UpdateImageParam_ = nullptr;
	sqlite3_stmt* sql_stmt_ExistKeypoints_ = nullptr;
	sqlite3_stmt* sql_stmt_WriteKeypoints_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateKeypoints_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadKeypoints_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadImageGPS_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateImageGPS_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateImagePose_ = nullptr;
	sqlite3_stmt* sql_stmt_ExistGroupID_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateInitCams_ = nullptr;
	sqlite3_stmt* sql_stmt_ResetInitCams_ = nullptr;
	
	// 特征匹配相关sql
	sqlite3_stmt* sql_stmt_ExistMatches_ = nullptr;
	sqlite3_stmt* sql_stmt_WriteMatches_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateMatches_ = nullptr;	

	// SfM相关sql
	sqlite3_stmt* sql_stmt_WriteSfMResult_ = nullptr;

	// MVS相关sql
	sqlite3_stmt* sql_stmt_ReadOriginalImageInfo_ = nullptr;		
	sqlite3_stmt* sql_stmt_ExistImageScaled_ = nullptr;
	sqlite3_stmt* sql_stmt_WriteImageScaledParam_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateImageScaledParam_ = nullptr;
	sqlite3_stmt* sql_stmt_WriteNeighbors_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadImageScaledParam_ = nullptr;
	sqlite3_stmt* sql_stmt_ExistDepthMap_ = nullptr;
	sqlite3_stmt* sql_stmt_WriteDepthMap_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateDepthMap_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadDepthMap_ = nullptr;
	sqlite3_stmt* sql_stmt_ExistMaskFilter_ = nullptr;	
	sqlite3_stmt* sql_stmt_WriteMaskFilter_ = nullptr;
	sqlite3_stmt* sql_stmt_UpdateMaskFilter_ = nullptr;
	sqlite3_stmt* sql_stmt_ReadMaskFilter_ = nullptr;

	bool Open(bool over_write = 0);
	void Close();
	bool CreatTables();
	bool DeleteTables();
	void PrepareSQLStatements();
	void FinalizeSQLStatements();
	bool BeginTransaction();	
	bool CommitTransaction();
	
	// 读取ID函数	
	bool ReadAllImageID(vector<unsigned>& IDs);
	bool ReadAllImageIDName(vector<unsigned>& IDs, vector<string>& names);
	bool ReadAllImageIDNameGroup(vector<unsigned>& IDs, vector<string>& names, vector<unsigned>& group_ids);
	bool ReadAllScaledImageID(vector<unsigned>& IDs);
	string ReadImageName(unsigned image_id);
	int ReadImageID(string name);

	// 特征提取函数
	bool WriteImageName(string name, int group_id = 0, int valid = 1);
	bool ExistImageName(string name);
	bool ExistGroupID(int group_id);
	bool WriteKeypoints(int image_id, cv::Mat& keys_data, cv::Mat& descs_data);
	bool ExistKeypoints(int image_id);
	bool ReadKeypoints(int image_id, cv::Mat& keys, cv::Mat& descriptors);
	bool UpdateImageGPS(int image_id, double lon, double lat, double alt, double gps_x, double gps_y, double gps_z);
	int ReadImageGPS(int image_id, double& lon, double& lat, double& alt, double& gps_x, double& gps_y, double& gps_z);
	bool UpdateImagePose(int image_id, double cx, double cy, double cz, cv::Matx33f& R);
	bool UpdateInitCams(int group_id, float fx, float fy, float u, float v, float k1 = -1, float k2 = -1, float k3 = -1, float k4 = -1, float k5 = -1);	
	bool ResetInitCams(int image_id, float fx, float fy, float u, float v, float k1 = -1, float k2 = -1, float k3 = -1, float k4 = -1, float k5 = -1);	
	bool WriteImageInfo(int image_id, int valid, int width, int height, float fx, float fy, float u, float v,						
						double gps_lon, double gps_lat, double gps_alt, double gps_x, double gps_y, double gps_z);

	// 特征匹配函数
	bool CleanMatches();
	bool WriteMatches(int image_id, vector<int>& match_data, vector<double>& model);
	bool ExistMatches(int image_id);

	// 初始化内参函数
	bool ResetInitCamsFromTxt(string camsTxtFile);
	bool ResetInitCamsFromBin(string camsBinFile);

	// SfM函数
	bool ReadAllMatches(ImageInfos& imageInfos, ImagePairMatches& imagePairMatches, bool initPoses = 0);
	bool WriteSfMResults(int image_id, int valid, float fx, float fy, float u, float v, float k1, float k2, float k3, float k4, float k5, 
						 double cx, double cy, double cz, cv::Matx33f& R);

	// MVS函数
	bool CleanImageScaled();
	bool ReadOriginalImageInfo(Image& image);
	bool ExistImageScaled(int image_id);
	bool ReadScaledImageInfo(Image& image, bool with_nrighbors = 0, bool with_points = 0);
	bool WriteImageScaledInfo(int image_id, string name, int valid, float scale, int width, int height, float fx, float fy, float u, float v,						
						float cx, float cy, float cz, cv::Matx33f& R);	
	bool WriteNeighbors(Image& image);
	bool CleanDepthmaps();
	bool ExistDepthMap(int image_id);
	bool WriteDepthMap(Image& image);
	bool ReadDepthMap(Image& image, bool with_depthmap = 0, bool with_confmap = 0, bool with_normalmap = 0);
	bool CleanMaskFilters();
	bool ExistMaskFilter(int image_id);
	bool WriteMaskFilter(Image& image);
	bool ReadMaskFilter(Image& image);
	unsigned long long CountMaskFiltersNum();
};